package actionHandlers;

/************************************************************
*   This class is designed to acknowledge a mouse click down 
*   (on the canvas) and append shapes to the canvas.shapeList
*   on mouse click up.
************************************************************/

import java.awt.*; //need for the paint
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import cuShapes.*;
import palette.CanvasManager;
import palette.CanvasWindow;

public class ShapeDrawListener implements MouseListener, MouseMotionListener {
	
	/**
	 * a flag that is set to true when we click the mouse button down, 
	 * and we want to draw an arrow not a new shape. 
	 */
	private boolean editingShape = false;
	//private ShapeList shapeList;
	
	/***********************************************************************************
	 *  Acknowledges any of the mouse buttons clicked down.  On that action one of
	 *  three things happen: First, looks to see if the position of the mouse is within 
	 *  bounds of any of the Connectable's rects for that current window's shapeList.  
	 *  	If yes, the currentShape is
	 *  set to an arrow, else
	 */
	public void mousePressed(MouseEvent e) {
		//first look for collision with a shape
		CanvasWindow currWin = ((CanvasWindow)CanvasManager.getInst().getSelectedFrame());
		try{
			currWin.getUndoStack().push(currWin.getShapeList().getDeepCopy());
		}
		catch(Exception ex){
			System.out.println("Error in deep copy");
		}
		for(PQShape x : currWin.getShapeList()){ 
			//check for resize or center
			if(x.hitRect(e.getPoint())){ 
				currWin.getShapeList().setCurrentShape(x);
				currWin.getShapeList().getCurrentShape().setWorkingRect(x.getWorkingRect());
				editingShape = true;
			}
			//look for bounding rect for an arrow draw
			else if(x.getRect().contains(e.getPoint())){
				Point p = x.getCenterRect().getLocation();
				currWin.getShapeList().setCurrentShape(new Arrow(p, Color.black));
				((Arrow)currWin.getShapeList().getCurrentShape()).setParent((Connectable)x);
				editingShape = true;
			}
		
		}		
		//this will draw a new shape to the screen
		if(!editingShape){
			/*
			 * If we are here, we need to ask the shape button what shape is selected,
			 *  then we 'new' it.  smart shape should do all this for us internally
			 *  when we call get shape.
			 *  after we get the shape, we give it a start and end.
			 */  
			currWin.getShapeList().setCurrentShape(CurrentShape.getNewShape(e.getPoint()));
			//currentShape.addPQShapeListener(new CurrentShapeListener());
		}
		currWin.getRedoStack().clear();
		currWin.getShapeList().update();
	}

	/*********************************************************
	 *   Here we are either setting the end for a new shape,
	 *      or moving an existing shape.  
	 *        Need a 'smart' currentShape. that can tell which
	 *        rect (tl,...,br) was selected, and how to resize.
	 *        
	 *        This method should just let the current shape that the final 
	 *          end location has been selected.
	 *          
	 */
	public void mouseReleased(MouseEvent e) {
		CanvasWindow currWin = ((CanvasWindow)CanvasManager.getInst().getSelectedFrame());
		// make sure currentShape isn't already in ShapeList
		if(currWin.getShapeList().getCurrentShape() instanceof cuShapes.Arrow){
			boolean foundConnection = false;
			for(PQShape s : currWin.getShapeList()){
				//do we hit another shape?
				if(s.getRect().contains((e.getPoint()))){
					//make sure its not us
					if (((Arrow)currWin.getShapeList().getCurrentShape()).getParent() != s) {
						((Arrow)currWin.getShapeList().getCurrentShape()).getParent().addConnection(((Connectable)s));
						currWin.getShapeList().setCurrentShape(s);
						foundConnection = true;
					}
				}
			}
			if(!foundConnection) {
				currWin.getShapeList().setCurrentShape(((Arrow)currWin.getShapeList().getCurrentShape()).getParent());
			}
		}
		else{
			if(!currWin.getShapeList().contains(currWin.getShapeList().getCurrentShape())) {
				currWin.getShapeList().add(currWin.getShapeList().getCurrentShape());
			}			
		}
		editingShape = false;
		currWin.getShapeList().update();
	}
	
	public void mouseClicked(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
	
	public void mouseDragged(MouseEvent e) {
		CanvasWindow currWin = ((CanvasWindow)CanvasManager.getInst().getSelectedFrame());
		currWin.getShapeList().getCurrentShape().moveWorkingRect(e.getPoint());
		currWin.getShapeList().update();
	}

	public void mouseMoved(MouseEvent e) {}
	
}
